package org.finmanager.data;

import org.finmanager.core.Category;

import java.io.File;
import java.io.PrintWriter;
import java.util.*;

import static org.finmanager.core.Constants.CATEGORY_DATA_FILE_NAME;

/**
 * Created by Kelvin on 21/3/2014.
 *
 * This is an abstract list containing Categories
 *
 * This class supports operations on the list
 */

//In our system, each category item is stored as LIST in a .txt file

public class CategoryList {
	public static final Category ALL_CATEGORIES_FLAG = new Category("All Categories");
	private ArrayList<Category> list = new ArrayList<Category>();

	public CategoryList() {
		loadFile();
	}

	// Load categories from the data file and store each category to a list
	// .txt file is used
	// Called in the start of the program
	private void loadFile() {
		try {
			File file = new File(CATEGORY_DATA_FILE_NAME);
			if (file.createNewFile()) {
				PrintWriter writer = new PrintWriter(file);
				writer.println(0);
				writer.close();
			}

			Scanner scanner = new Scanner(file);
			int numOfItems = Integer.parseInt(scanner.nextLine());
			for (int i = 0; i < numOfItems; ++i) {
				String name = scanner.nextLine();
				Boolean favourite = Boolean.parseBoolean(scanner.nextLine());

				Category category = new Category(name, favourite);

				list.add(category);
			}
			scanner.close();
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	// Save each category in the list to the data file
	// Called every time the list is changed
	private void saveFile() {
		try {
			File file = new File(CATEGORY_DATA_FILE_NAME);
			file.createNewFile();

			PrintWriter writer = new PrintWriter(file);

			writer.println(list.size());
			for (Category category : list) {
				writer.println(category.getName());
				writer.println(category.isFavourite());
			}
			writer.close();
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	//add a category
	public void addCategory(Category category) {
		list.add(category);
		saveFile();
	}

	//delete a category
	public void deleteCategory(int index) {
		list.remove(index);
		saveFile();
	}

	// Return the category of a certain name
	// Called when String category name is translated into Category type
	public Category findCategory(String name) {
		try {
			for (Category c : list) {
				if(c.getName().equals(name)) {
					return c;
				}
			}
			if (name.equals(ALL_CATEGORIES_FLAG.getName())) {
				return ALL_CATEGORIES_FLAG;
			}
			throw new Exception("Category not found!");
		} catch (Exception e) {
			e.getMessage();
			e.printStackTrace();
		}
		return null;
	}

	// Return a list of favourite categories
	// Called when constructing the favourite bar on ItemManagerUI
	public List<Category> getFavouriteCategories() {
		ArrayList<Category> favourite = new ArrayList<Category>();

		for (Category c : list) {
			if (c.isFavourite()) {
				favourite.add(c);
			}
		}

		return Collections.unmodifiableList(favourite);
	}

	// Return the number of favourite categories
	// The program do not allow users to add too much favourite categories
	public int getFavouriteCategoriesCount() {
		int i = 0;
		for (Category c : list) {
			if (c.isFavourite()) {
				++i;
			}
		}
		return i;
	}

	//When using the Budget function, user may view ITEMS under certain category
	public List<Category> getFilteredCategories() {
		ArrayList<Category> filtered = new ArrayList<Category>();

		for (Category c : list) {
			if (c.isFilterSelected()) {
				filtered.add(c);
			}
		}

		return Collections.unmodifiableList(filtered);
	}

	//Let user reset the filtered category to view ITEMS 
	public void resetFilterSelection() {
		for (Category c : list) {
			c.resetFilterSelection();
		}
	}

	//count the total no. of categories in the .txt file
	public int getCategoryCount() {
		return list.size();
	}

	public Category getCategory(int index) {
		return list.get(index);
	}

	public void toggleFavourite(int index) {
		list.get(index).toggleFavourite();
		saveFile();
	}

	public void toggleFilterSelection(int index) {
		list.get(index).toggleFilterSelection();
	}

	public List<Category> getList() {
		return Collections.unmodifiableList(list);
	}
}
